import Global, { PlayerFrame, Player } from "./Global";
import HeroMgr from "./Hero";

const { ccclass, property } = cc._decorator;

@ccclass
export default class NewClass extends cc.Component {

    /**
     * 存储所有玩家的信息，格式{playerid:{}}
     */
    heroObjects: any;  
    playerFrameItems: any;
    timestamp: number;
    frameId: number;

    initState() {
        // 初始化玩家信息
        let playerList = Global.room.roomInfo.playerList;
        this.heroObjects = {};
        for (let i = 0; i < playerList.length; i++) {
            let hero: Hero = new Hero();
            let playerId = playerList[i].id;
            hero.playerId = playerId;
            let node = Global.playerNodes[playerId];
            let hMgr = node.getComponent("Hero");
            hero.teamId = hMgr.teamId;
            hero.damage = hMgr.damage;
            hero.defence = hMgr.defence;
            hero.blood = hMgr.blood;
            hero.totalBlood = hMgr.totalBlood;

            this.heroObjects[playerId] = hero;
            this.heroObjects[playerId].x = Global.playerPos[playerId].x;
            this.heroObjects[playerId].y = Global.playerPos[playerId].y;

            //初始化子弹
            let bulletsPool = new Array<Bullet>();
            for (let i = 0; i < 20; i++) {
                let b = new Bullet();
                bulletsPool.push(b);
            }
            hero.bulletsPool = bulletsPool;
            hero.bullets = new Array<Bullet>();
        }
        this.timestamp = 0;
        this.frameId = 0;


    }

    //计算逻辑帧，帧率默认15
    calFrame(frame: MGOBE.types.Frame, frameRate: number) {
        // 初始化随机种子
        const seed = frame.ext.seed + frame.id;
        MGOBE.RandomUtil.init(seed);

        // if (frame.items.length > 0) {
        //     cc.log(`帧长度：${frame.items.length}`)
        //     cc.log(frame.items)
        // }

        //一帧的时间差
        let deltaTime = Math.floor((1000 / frameRate) * 1000) / 1000;

        let playerList = Global.room.roomInfo.playerList;
        let allItems: object = {};     //存储当前帧所有玩家的帧消息,格式{playerid:[]}
        for (let i = 0; i < playerList.length; i++) {
            allItems[playerList[i].id] = new Array();
        }
        // 处理帧item
        for (let i = 0; i < frame.items.length; i++) {
            let frameItem = frame.items[i];
            allItems[frameItem.playerId].push(frameItem);
        }

        for (const key in allItems) {
            if (allItems.hasOwnProperty(key)) {
                const frameItems = allItems[key];
                //处理方式一：当前逻辑帧可能会有多个当前玩家的操作指令，依次处理每个指令
                for (let i = 0; i < frameItems.length; i++) {
                    const frameItem = frameItems[i];
                    let playerFrame: PlayerFrame = frameItem.data as PlayerFrame;
                    this.handleFrame(playerFrame, deltaTime);
                }
                //处理方式二：直接取当前玩家的最后一个操作指令
                // const frameItem = frameItems[frameItems.length - 1];
                // if(!frameItem) continue;
                // let playerFrame: PlayerFrame = frameItem.data as PlayerFrame;
                // this.handleFrame(playerFrame, deltaTime);
            }
        }

        // 更新时间
        this.timestamp = frame.time;
        this.frameId = frame.id;



    }

    //检测子弹是否和敌方玩家碰撞
    collisionHero(bullet: Bullet, playerList) {
        let heroSelf = bullet.hero;

        for (let i = 0; i < playerList.length; i++) {
            let hero: Hero = this.heroObjects[playerList[i].id];
            //友军无伤害
            if (hero.isDie || hero.teamId == heroSelf.teamId) {
                continue;
            }

            let offsetX = (hero.width + bullet.width) / 2;
            let offsetY = (hero.height + bullet.height) / 2;

            let collide = Math.abs(bullet.x - hero.x) <= offsetX && Math.abs(bullet.y - hero.y) <= offsetY;
            if (collide) {
                //计算伤害
                this.calDamage(heroSelf,hero);
                cc.log("碰撞了")
                cc.log(`碰撞时,子弹位置:${bullet.x},${bullet.y};碰撞玩家位置:${hero.x},${hero.y}`)
                return true;
            }
        }
        return false;
    }

    /**
    * 计算伤害
    * @param self 
    * @param enemy 
    */
    calDamage(self: Hero, enemy: Hero) {
        if (self.isDie || enemy.isDie) {
            return;
        }
        let damage = self.damage;
        if(this.isCrit()){
            damage = self.damage * 2;
            cc.log(`触发暴击了!!暴击伤害:${damage}`)
        }
        let minus = damage - enemy.defence;
        if (minus >= 0) {
            enemy.blood -= minus;
        }
        if (enemy.blood <= 0) {
            enemy.blood = 0;
            enemy.isDie = true;
            //通知玩家开始复活倒计时
            cc.game.emit("reborn",enemy.playerId);
        }
        cc.log(`玩家坦克血量:${enemy.blood}`)
    }

    /**
     * 是否触发暴击，暴击伤害翻倍
     */
    isCrit(){
        let r = Math.floor(MGOBE.RandomUtil.random() * 100);
        cc.log(`随机数值为:${r}`)
        if( r < 20){
            return true;
        }
        return false;
    }

    handleFrame(pf: PlayerFrame, dt: number) {
        let playerId = pf.playerId;

        let hero: Hero = this.heroObjects[playerId];

        if (hero.isDie) {
            return;
        }
        //处理移动
        if (pf.isMoving != undefined) {
            hero.isMoving = pf.isMoving;
        }
        if (pf.moveSpeed != undefined) {
            hero.moveSpeed = pf.moveSpeed;
        }
        if (pf.moveRadian != undefined) {
            hero.moveRadian = pf.moveRadian;
        }
        //处理射击
        if (pf.rotateRadian != undefined) {
            hero.rotateRadian = pf.rotateRadian;
        }

        let frameShooting = null;
        if (pf.isShooting != undefined) {
            frameShooting = pf.isShooting;
        }

        /**  如果当前玩家射击状态为false，并且传过来的是true，则开始射击。不能重复射击，会导致重复setInterval
            如果当前玩家射击状态为true，并且传过来的是false，则停止射击。clearInterval
        */
        if (!hero.isShooting && frameShooting) {
            hero.startShoot(dt);
        }
        // else if (hero.isShooting && !frameShooting) {
        //     hero.terminateShoot();
        // }
        hero.isShooting = frameShooting;

        //处理碰撞、子弹销毁
        let playerList = Global.room.roomInfo.playerList;
        for (let i = 0; i < playerList.length; i++) {
            let hero: Hero = this.heroObjects[playerList[i].id];
            // if(hero.playerId == MGOBE.Player.id){
            //     cc.log(hero.bullets.length)
            // }
            for (let i = 0; i < hero.bullets.length; i++) {
                let bullet = hero.bullets[i];
                if (bullet == undefined) return;
                if (bullet.distance > bullet.range || this.collisionHero(bullet, playerList)) {
                    hero.bulletsPool.push(bullet);
                    delete hero.bullets[i]; //先把子弹对象设为undefined，不改变数组长度，不然会导致逻辑和表现的子弹数组对应不上
                }
            }
        }

        //更新玩家和子弹位置等信息
        hero.update(dt / 1000);

    }

    //逻辑拷贝到表现层
    syncToView() {
        let heroObjects = this.heroObjects;
        for (const key in heroObjects) {
            if (heroObjects.hasOwnProperty(key)) {
                const hero = heroObjects[key];
                this.copyHero(hero, key);
            }
        }
    }

    //拷贝玩家状态
    copyHero(hero: Hero, playerId: string) {
        // cc.log(`玩家逻辑位置:{${hero.x},${hero.y}}`)
        let pNode: cc.Node = Global.playerNodes[playerId];
        let hMgr: HeroMgr = pNode.getComponent("Hero");
        // --- 处理移动  ---//
        hMgr.moveSpeed = hero.moveSpeed;
        hMgr.setIsMoving(hero.isMoving);

        hMgr.timestamp = this.timestamp;
        hMgr.updatePosition(hero.x, hero.y, hero.moveRadian);
        // --- 处理右摇杆旋转和射击  ---//
        //弧度转角度
        let rstickRotation = cc.misc.radiansToDegrees(hero.rotateRadian);
        hMgr.setRotateRadian(hero.rotateRadian);
        hMgr.setWeaponRotation(-rstickRotation);

        let isShooting = hero.isShooting;
        hMgr.setIsShooting(isShooting);
        hMgr.copyBullets(hero.bullets);

        //同步伤害
        hMgr.updateBlood(hero.blood);
        hMgr.isDie = hero.isDie;

    }
}

export class Hero {
    isMoving: boolean = false;
    isShooting: boolean = false;
    rotateRadian: number = 0;
    moveRadian: number = 0;
    bulletsPool: Array<Bullet> = null;
    bullets: Array<Bullet> = null;
    shootTime: number = 0.2; //射击间隔
    intervalHandle: number = 0;
    bNomalDegree: number = 90; //初始子弹角度

    //------ 坦克属性 ----//
    totalBlood: number = 0;
    teamId: string = null;
    isDie: boolean = false;
    playerId: string = null;
    moveSpeed: number = 0;
    blood: number = 0;
    damage: number = 0;
    defence: number = 0;
    lv: number = 0;

    x: number = 0;
    y: number = 0;
    width: number = 64;
    height: number = 64;

    weapon = {
        width: 74, height: 35, anchorX: 0.2, anchorY: 0.5
    };

    update(dt: number) {
        if (this.isMoving) {
            //移动角色
            this.x += this.moveSpeed * Math.floor(Math.cos(this.moveRadian) * 1000) / 1000 * dt;
            this.y += this.moveSpeed * Math.floor(Math.sin(this.moveRadian) * 1000) / 1000 * dt;
        }
        for (let i = 0; i < this.bullets.length; i++) {
            let bullet = this.bullets[i];
            if (bullet == undefined) return;
            bullet.update(dt);
        }
    }

    //开始射击
    startShoot(dt) {
        // cc.log("开始射击了");
        this.doShoot(dt);
        // 启动一个定时器
        // var lastUpdate = Date.now()
        // self.intervalHandle = setInterval(function () {
        //     var now = Date.now()
        //     var dlt = now - lastUpdate
        //     lastUpdate = now
        //     updateTime(dlt)
        // });
        // var nowTime = 0;
        // var updateTime = function (dlt) {
        //     nowTime += dlt;
        //     if (nowTime >= self.shootTime * 1000) {
        //         self.doShoot(dt);
        //         nowTime = 0;
        //     }
        // }

    }

    /**
     * 终止射击
     */
    terminateShoot() {
        cc.log("结束射击了");
        // clearInterval(this.intervalHandle);
    }

    /**
    * 从子弹池中取出一个子弹进行射击
    */
    doShoot(dt) {
        let bullet: Bullet = null;
        // cc.log("bulletsPool length:" + this.bulletsPool.length);
        if (this.bulletsPool.length > 0) {
            bullet = this.bulletsPool.shift();
        } else {
            bullet = new Bullet();
        }

        bullet.initBullet(this.rotateRadian, this.bNomalDegree, this);

        //计算炮头到原点的长度
        let length = this.weapon.width * (1 - this.weapon.anchorX);
        // 要加上hero的x、y坐标
        let deltaX = length * Math.cos(this.rotateRadian);
        let deltaY = length * Math.sin(this.rotateRadian);
        let posx = this.x + deltaX;
        let posy = this.y + deltaY;
        cc.log(`坦克位置:${this.x},${this.y}`)
        cc.log(`逻辑子弹出生位置:${posx},${posy}`);
        bullet.startPosx = deltaX;
        bullet.startPosy = deltaY;

        bullet.teamId = this.teamId;
        bullet.x = posx;
        bullet.y = posy;
        bullet.update(dt / 1000); //一个逻辑帧后的子弹位置
        this.bullets.push(bullet);
    }



}

export class Bullet {
    //子弹速度
    speed: number = 0;
    //子弹弧度
    bulletRadian: number = 0;
    //射程
    range = 700;
    //子弹所属队伍
    teamId: string = null;

    distance = 0;
    distanceX = 0;
    distanceY = 0;
    hero: Hero = null;

    x: number = 0;
    y: number = 0;
    width: number = 5;
    height: number = 30;

    //子弹偏移量
    startPosx: number = 0;
    startPosy: number = 0;

    initBullet(rotateRadian: number, bNomalDegree: number, hero: Hero) {
        this.hero = hero;

        this.distance = 0;
        this.speed = 800;
        this.bulletRadian = rotateRadian;

    }

    update(dt) {
        this.distance += this.speed * dt;
        this.x += this.speed * Math.cos(this.bulletRadian) * dt;
        this.y += this.speed * Math.sin(this.bulletRadian) * dt;

    }


}